import 'dart:async';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:dio/io.dart';

// import 'package:dio_proxy_plugin/dio_proxy_plugin.dart';
// import 'package:flutter/services.dart';
import 'package:flutter_09_game/config/app_config.dart';
import 'package:flutter_09_game/http/http_connection_check.dart';
import 'package:flutter_09_game/http/http_core.dart';
import 'package:flutter_09_game/http/http_export.dart';
import 'package:flutter_09_game/http/http_handler.dart';
import 'package:flutter_09_game/http/ui/http_loading.dart';
import 'package:flutter_09_game/http/ui/http_toast.dart';
import 'package:flutter_09_game/utils/log/utils_log.dart';
import 'package:get/get_utils/get_utils.dart';
import 'package:flutter_09_game/generated/locales.g.dart';

import 'http_log_interceptor.dart';
import 'request_interceptor.dart';
import 'response_interceptor.dart';

class HttpManager {
  static final HttpManager _instance = HttpManager._();

  factory HttpManager() => _instance;

  late Dio _dio;

  Function(int? code)? errorCodeListener;

  Dio getDio() {
    return _dio;
  }

  HttpManager._() {
    BaseOptions baseOptions = BaseOptions(
      baseUrl: AppConfig.baseUrl,
      connectTimeout: const Duration(milliseconds: 30 * 1000),
      sendTimeout: const Duration(milliseconds: 30 * 1000),
      receiveTimeout: const Duration(milliseconds: 30 * 1000),
      contentType: Headers.formUrlEncodedContentType,
      //'application/json;Charset=UTF-8',
      //'application/json;Charset=UTF-8',
      // application/x-www-form-urlencoded

      responseType: ResponseType.json,
    );

    _dio = Dio(baseOptions);

    _dio.interceptors.add(RequestInterceptor());
    _dio.interceptors.add(ResponseInterceptor());
    // (dio.httpClientAdapter as IOHttpClientAdapter).onHttpClientCreate = (HttpClient client) {
    //   // 忽略所有证书验证错误
    //   client.badCertificateCallback = (X509Certificate cert, String host, int port) {
    //     print('⚠️ 忽略证书验证: $host');
    //     return true; // 返回 true 表示忽略证书错误
    //   };
    //   return client;
    // };
    // (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
    //   client.badCertificateCallback = (X509Certificate cert, String host, int port) => true;
    //   client.findProxy = (uri) => 'DIRECT';
    //   return client;
    // };
    _dio.httpClientAdapter = IOHttpClientAdapter(
      createHttpClient: () {
        final client = HttpClient();
        client.badCertificateCallback =
            (X509Certificate cert, String host, int port) {
          clog('⚠️ 忽略证书验证: $host');
          return true; // 返回 true 表示忽略证书错误
        };
        // ✅ 禁止走系统代理（关键）
        // client.findProxy = (uri) => 'DIRECT';
        return client;
      },

      // 可选：关闭自动重定向
      // validateCertificate: (cert, host, port) => true,
    );

    /// 非正式环境拦截日志打印
    if (!const bool.fromEnvironment("dart.vm.product")) {
      _dio.interceptors.add(HttpLogInterceptor(requestHeader: true));
    }
  }

  setBaseUrl(String baseUrl) {
    _dio.options.baseUrl = baseUrl;
  }

  Future<HttpResponse> get<T>(api,
      {params,
      T Function(Map<String, dynamic>)? fromJson,
      void Function(HttpResponse response)? handleError,
      HttpUIType uiType = HttpUIType.toast,
      CancelToken? cancelToken}) async {
    return _showUI(
            _dio.getRequest(api,
                data: params,
                queryParameters: params,
                cancelToken: cancelToken),
            uiType)
        .handler<T>(fromJson, handleError, errorCodeListener);
  }

  Future<HttpResponse> post<T>(api,
      {params,
      T Function(Map<String, dynamic>)? fromJson,
      void Function(HttpResponse response)? handleError,
      HttpUIType uiType = HttpUIType.toast,
      CancelToken? cancelToken}) async {
    // print('dasljdlk   ${params['images']}   ${params['images'] is String}');
    return _showUI(
            _dio.postRequest(api, data: params, cancelToken: cancelToken),
            uiType)
        .handler<T>(fromJson, handleError, errorCodeListener);
  }

  Future<HttpResponse> put<T>(
    api, {
    params,
    T Function(Map<String, dynamic>)? fromJson,
    void Function(HttpResponse response)? handleError,
    HttpUIType uiType = HttpUIType.toast,
  }) async {
    return _showUI(_dio.putRequest(api, data: params), uiType)
        .handler(fromJson, handleError, errorCodeListener);
  }

  Future<HttpResponse> _showUI(Future<HttpResponse> future, HttpUIType uiType) {
    switch (uiType) {
      case HttpUIType.loading:
        future = future.loading();
        break;
      case HttpUIType.toast:
        future = future.toast();
        break;
      case HttpUIType.loadingAndToast:
        future = future.loading().toast();
        break;
      case HttpUIType.none:
        break;
    }
    return future;
  }

  Future putBytes(
    String url,
    List<int> bytes, {
    ProgressCallback? onSendProgress,
  }) async {
    try {
      Response response = await _dio.put(url,
          data: bytes,
          onSendProgress: onSendProgress,
          options: Options(
              responseType: ResponseType.bytes, contentType: "image/jpeg"));
      clog(
          "====>[put] response: ${response.statusCode.toString()} ${response.data.toString()}");
      if (response.statusCode == 200) {
        return HttpResponse(
            data: response.data,
            code: response.statusCode,
            msg: response.statusMessage);
      } else {
        return Future.error(response.statusMessage.toString());
      }
    } on DioException catch (e) {
      clog("====>[put] error: $e");
      return Future.error(e.message.toString());
    }
  }

  Future upload({
    required String url,
    required String key,
    required String token,
    required String filePath,
    ProgressCallback? onSendProgress,
  }) async {
    try {
      var file = await MultipartFile.fromFile(filePath);
      FormData formData = FormData.fromMap({
        'token': token, // 上传凭证
        'key': key,
        'file': file, // 文件
      });
      Response response =
          await _dio.post(url, data: formData, onSendProgress: onSendProgress);
      if (response.statusCode == 200) {
        return HttpResponse(
            data: response.data,
            code: response.statusCode,
            msg: response.statusMessage);
      } else {
        return Future.error(response.statusMessage.toString());
      }
    } on DioException catch (e) {
      clog("====> error: $e", tag: "upload");
      return Future.error(e.message.toString());
    }
  }

/*//  图片格式限制jpg或jpeg,文件名必须带后缀
  Future<HttpResponse> upload<T>({
    required List<int> fileData,
    ProgressCallback? onSendProgress,
    CancelToken? cancelToken,
    required String fileName,
    T Function(Map<String, dynamic>)? fromJson,
  }) async {
    var file = MultipartFile.fromBytes(fileData, filename: fileName);
    FormData formData = FormData.fromMap({
      'file': file,
    });
    return _dio
        .postRequest(API.uploadFile,
        data: formData, options: Options(extra: {"isUploadFile": true}), onSendProgress: onSendProgress, cancelToken: cancelToken)
        .handler(fromJson, null, errorCodeListener);
  }*/

  Future<HttpResponse> download({
    required String url,
    required String savePath,
    Map<String, dynamic>? queryParameters,
    ProgressCallback? onReceiveCallback,
    CancelToken? cancelToken,
  }) async {
    late HttpResponse httpResponse;
    var isComplete = false;
    await _dio.download(url, savePath,
        cancelToken: cancelToken,
        options: Options(
          sendTimeout: const Duration(seconds: 60),
          receiveTimeout: const Duration(seconds: 300),
          extra: {"isUploadFile": true},
        ), onReceiveProgress: (count, total) {
      onReceiveCallback?.call(count, total);
      isComplete = count == total;
    }).then((response) {

      clog('dalsjdlkasjd   ${response.headers.map}');
      httpResponse =
          HttpResponse(code: HttpCode.code0, msg: 'success', data: {});
    }).catchError((error) async {
      httpResponse = await _handleDioException(error);
    }).whenComplete(() async {
      if (httpResponse.isSuccess) {
        httpResponse = HttpResponse(
            code: HttpCode.code0,
            msg: isComplete ? "success" : LocaleKeys.downloadIncomplete.tr,
            data: isComplete ? savePath : null);
      }
    });
    return httpResponse;
  }

  Future<HttpResponse> _handleDioException(error) async {
    DioException exception = error;
    DioExceptionType type = exception.type;
    // if (type == DioExceptionType.connectionError && isNoNetWork == false) {
    //   await HttpConnectionCheck.checkNetWork(listen: false);
    // }
    // if (type == DioExceptionType.unknown) {
    //   await HttpConnectionCheck.checkNetWork(listen: false);
    //   if (isNoNetWork) {
    //     type = DioExceptionType.connectionError;
    //   }
    // }
    HttpResponse response = HttpResponse(type: type, msg: exception.message);
    response = HttpHandleError.adjust(response, exception: exception);
    return response;
  }
}
